/**
 * Created by cj on 2017/5/8.
 */

// Flyweight object
var CoffeeOrder = {
// Interfaces
    serveCoffee: function (context) {
    },
    getFlavor: function () {
    }
};
// ConcreteFlyweight object that creates ConcreteFlyweight
// Implements CoffeeOrder
function CoffeeFlavor(newFlavor) {
    var flavor = newFlavor;
// If an interface has been defined for a feature
// implement the feature
    if (typeof this.getFlavor === "function") {
        this.getFlavor = function () {
            return flavor;
        };
    }
    if (typeof this.serveCoffee === "function") {
        this.serveCoffee = function (context) {
            console.log("Serving Coffee flavor "
                + flavor
                + " to table number "
                + context.getTable());
        };
    }
}

Function.prototype.implementsFor = function( parentClassOrObject ){
    if ( parentClassOrObject.constructor === Function ) {
        // Normal Inheritance
        this.prototype = new parentClassOrObject();
        this.prototype.constructor = this;
        this.prototype.parent = parentClassOrObject.prototype;
    } else {
        // Pure Virtual Inheritance
        this.prototype = parentClassOrObject;
        this.prototype.constructor = this;
        this.prototype.parent = parentClassOrObject;
    }
    return this;
};

// Implement interface for CoffeeOrder
CoffeeFlavor.implementsFor(CoffeeOrder);
// Handle table numbers for a coffee order
function CoffeeOrderContext(tableNumber) {
    return {
        getTable: function () {
            return tableNumber;
        }
    };
}
function CoffeeFlavorFactory() {
    var flavors = {},
        length = 0;
    return {
        getCoffeeFlavor: function (flavorName) {
            var flavor = flavors[flavorName];
            if (flavor === undefined) {
                flavor = new CoffeeFlavor(flavorName);
                flavors[flavorName] = flavor;
                length++;
            }
            return flavor;
        },
        getTotalCoffeeFlavorsMade: function () {
            return length;
        }
    };
}
